//------------------------------------------------------------
//  Filename: gaoya_proc.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2016-10-10 17:50
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module GAOYA_PROC ( 
    input clk,  
    input rst, 

    input  wire [31:0] gaoya_time,  // in 1/100 us ,self clear
    input  wire [7:0]  gaoya_force,  
    input  wire [31:0] gaoya_ctrl_time,  
    input  wire [7:0 ] gaoya_ctrl_force,  
    
    output reg         dac_sclk    ,
    output reg         dac_sdata   ,
    output reg         dac_load    ,
    output reg         gaoya
);    
//--------------------------------------------------------
localparam BASE_DIV = 7;
//--------------------------------------------------------
wire[1:0] dac_chanel = 2'b00;
wire      dac_rng    = 1'b0;
//--------------------------------------------------------
reg  dac_serial_data;
reg  dac_serial_clk ;
reg  dac_serial_load;
//--------------------------------------------------------
reg[7:0]  dac_data_prev;
//--------------------------------------------------------
reg[31:0] gaoya_time_load;
reg[7:0]  gaoya_force_load;
//--------------------------------------------------------
always @(posedge clk) dac_data_prev <= gaoya_force_load;
//--------------------------------------------------------
wire data_change = (dac_data_prev == gaoya_force_load)?1'b0:1'b1;
//--------------------------------------------------------
reg[16:0] counter_driver;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        counter_driver <= 16'b0;    
    end 
    else if(data_change) begin 
        counter_driver <= {16'hf,{(BASE_DIV + 2){1'b0}}}; 
    end 
    else if(counter_driver > 0) begin
        counter_driver <= counter_driver - 1;
    end
end 
//--------------------------------------------------------
reg[31:0] dac_clk_shifter;
reg[31:0] dac_data_shifter;
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        dac_clk_shifter  <= 32'b0;     
        dac_data_shifter <= 32'b0;     
    end 
    else if(data_change) begin  
        dac_clk_shifter  <= 32'haaaaa800;     
        dac_data_shifter <= {dac_chanel[1:0],dac_rng,gaoya_force_load[7:0],21'b0};     
    end 
    else begin
        dac_clk_shifter  <= (counter_driver[BASE_DIV:0]=={(BASE_DIV+1){1'b1}})?{dac_clk_shifter[30:0],1'b0}:dac_clk_shifter;     
        dac_data_shifter <= (counter_driver[(BASE_DIV + 1):0]=={(BASE_DIV+2){1'b1}})?{dac_data_shifter[30:0],1'b0}:dac_data_shifter;     
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        dac_serial_clk  <= 1'b0;
        dac_serial_data <= 1'b0;            
    end 
    else begin 
        dac_serial_clk  <= (counter_driver[BASE_DIV:0]=={(BASE_DIV+1){1'b1}})?dac_clk_shifter[31]:dac_serial_clk;
        dac_serial_data <= (counter_driver[(BASE_DIV + 1):0]=={(BASE_DIV+2){1'b1}})?dac_data_shifter[31]:dac_serial_data;            
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        dac_serial_load <= 1'b0;    
    end 
    else if(counter_driver == 0) begin
        dac_serial_load <= 1'b0;
    end	 
    else if(counter_driver[(BASE_DIV + 5):(BASE_DIV + 2)] < 2) begin
        dac_serial_load <= 1'b0;
    end	 
    else begin
        dac_serial_load <= 1'b1; 
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        dac_sdata <= 0;
        dac_sclk  <= 0;
        dac_load  <= 0;           
    end 
    else begin 
        dac_sdata <= ~dac_serial_data;
        dac_sclk  <= ~dac_serial_clk ;
        dac_load  <= ~dac_serial_load;                   
    end 
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        gaoya_time_load <= 32'b0;    
    end 
    else if(gaoya_time > 0) begin 
        gaoya_time_load <= gaoya_time;    
    end 
    else begin
        gaoya_time_load <= gaoya_ctrl_time;    
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        gaoya_force_load <= 8'b0;        
    end 
    else if(gaoya_force[7:0] > 0)begin 
        gaoya_force_load <= gaoya_force;
    end 
    else begin
        gaoya_force_load <= gaoya_ctrl_force;
    end
end 
//--------------------------------------------------------
always @(posedge clk,posedge rst) begin
    if(rst)begin 
        gaoya <= 1'b1;
    end 
    else begin 
        gaoya <= (gaoya_time_load > 0)?1'b0:1'b1;
    end 
end  

endmodule
